package com.friends.oss.web;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.friends.common.tools.constant.ResultCode;
import com.friends.common.web.annotation.AccessToken;
import com.friends.common.web.exception.AlisignException;
import com.friends.oss.OssTools;
import com.friends.oss.constant.AliOssDir;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * oss对象上传时需首先调用该请求获取相关数据及签名
 * Created by xiajiangge on 2017/4/13.
 */
@RestController
@RequestMapping("/osspolicy")
public class OssPolicyController {

    @Autowired
    private OssTools ossTools;
    /**
     * oss对象上传时需首先调用该请求获取相关数据及签名
     * @param dir        目录（文件名前缀）
     * @param callback   回调函数
     * @return
     * @throws AlisignException
    */
    @AccessToken(valid = true,userIdParamName = "loginid",accessTokenParamName = "accessToken")
    @RequestMapping(value="/getPolicy.html")
    public Object getPolicy(String dir, String callback) throws AlisignException {

        //判断dir是否合法
        if(!AliOssDir.isExists(dir)) {
            throw new AlisignException("该目录不是合规路径");
        }

        Map<String, String> resultMap = genRespMap(dir);
        resultMap.put("code", ResultCode.SUCCESS.getCode());
        resultMap.put("msg",ResultCode.SUCCESS.getMsg());

        if(StringUtils.isEmpty(callback)){
            return resultMap;
        }
        //处理带回调函数的jsonp返回
        MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(resultMap);
        mappingJacksonValue.setJsonpFunction(callback);
        return mappingJacksonValue;
    }

    private Map<String,String> genRespMap(String dir) throws AlisignException{

        String protocol = ossTools.getProtocol();
        String bucket = ossTools.getBucketsour();
        String endpoint = ossTools.getEndpoint();
        String accessId = ossTools.getAccessId();
        long expireTime = ossTools.getExpireTime();
        long filesizeLimit = ossTools.getFilesizeLimit();

        String host = protocol + "://" + bucket + "." + endpoint;
        OSSClient client = ossTools.getOssClient();

        try{
            //生成Policy签名数据
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, filesizeLimit);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = client.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = client.calculatePostSignature(postPolicy);
            //构建返回
            Map<String, String> resultMap = new LinkedHashMap<String, String>();
            resultMap.put("accessid", accessId);
            resultMap.put("policy", encodedPolicy);
            resultMap.put("signature", postSignature);
            resultMap.put("dir", dir);
            resultMap.put("host", host);
            resultMap.put("expire", String.valueOf(expireEndTime / 1000));
            return resultMap;
        }catch (Exception e){
            throw new AlisignException("云端签名发生错误");
        }
    }

    @AccessToken(valid = true,userIdParamName = "loginid",accessTokenParamName = "accessToken")
    @RequestMapping(value="/delOssObj.html")
    public Map<String,String> delOssObj(String key,String bucket){

        Map<String, String> resultMap = new HashMap<String, String>();
        try{
            ossTools.delOssObj(key,bucket);
            resultMap.put("code", ResultCode.SUCCESS.getCode());
            resultMap.put("msg",ResultCode.SUCCESS.getMsg());
            return resultMap;
        }catch (Exception e){
            resultMap.put("code", ResultCode.COMMONERROR.getCode());
            resultMap.put("msg",ResultCode.COMMONERROR.getMsg());
            return resultMap;
        }

    }


}
